Spring cloud GatewayFilter and GlobalFilter

过滤器之所以在网关中存在,是因为在微服务系统中,服务提供者非常的多,因此如果在每个服务中都有诸如鉴权、限流以及日志输出等则会占用服务的消耗(也就是说每个服务我都要写一遍这些功能,则会让开发很烦躁)因此可以直接通过网关来进行处理。

网关应可以处理鉴权、限流等工作

PRE and POST

PRE

根据请求的生命周期,在 Gateway 中,过滤器会分为 PRE、POST 两种,其中 PRE 代表 在路由执行之前的请求 执行该过滤,因此主要应用在参数校验、鉴权、流量监控、日志输出、协议转换功能。

POST

POST 主要是在 请求被路由跳到微服务之后所执行 的过滤器,因此这种过滤器可以实现出相应头(HTTP Header)以及收集统计信息和指标、响应转发、日志输出、流量监控等功能。

GatewayFilter and GlobalFilter

GatewayFilter (网关过滤器)

过滤器分为两类,其中网关过滤器(GatewayFilter)只会在 单个路由或者分组路由中。网关过滤器是一种 可以修改请求传入的 HTTP 请求或输出 HTTP 相应 的特定路由使用,Gateway 内置了 20 多种网关过滤器工厂来编写网关过滤器:

Id Name type Info
1 AddRequestHeader Request 用于在请求头中添加自定义的键值对
2 AddRequestParameter Request 用于在请求参数中添加请求参数的键值对
3 AddResponseHeader Response 用于在相应头中添加
4 Hystrix 断路器 用于将断路器引入网关路由中,可以让服务免受级联故障影响,并在故障时提供回退响应(使用时需要使用名为 HystrixCommand 的参数)
5 PrefixPath Path 用于使用简单的 Prefix
6 PreserveHostHeader Header 设置路由过滤器的请求属性,检查是否发送原主机头或由 HTTP 客户端确定主机头
7 RequestRateLimiter Request 用于确定当前请求是否继续(如果不允许则会返回 HTTP 429 - Too Many Request
8 RedirectTo Request 用于接受请求的状态和 URL 参数(该状态是一个重定向的 300 系列 HTTP 代码,类似与 301。但 URL 是 Location 头部的值)
9 RemoveNonProxyHeaders Headers 从转发的请求中删除请求头
10 RemoveRequestHeader Request 通过请求头名删除请求头
11 RemoveResponseHeader Response 通过响应头名删除响应头
12 RewritePath Path 通过 Java 正则表达式重写请求路径
13 SaveSession Session 在转发下游调用之前,强制执行保存 Session 的操作
14 SecureHeaders Headers 为响应头添加安全头
15 SetPath Path 该方法允许通过路径的模板段来操作请求路径,使用 Spring 的 URI 模板,支持多种匹配
16 SetResponseHeader Response 需要通过 Key-Value 对来设置响应头
17 SetStatus Response 用于设置请求响应状态,但需要 Status 参数(需要有效的 Spring HttpStatus,例如整形的 404 或枚举类型字符串 NOT_FOUND
18 StripPrefix Request 用于剥离前缀(需要 parts 参数,用于表明请求被发送到下游之前从请求路径中所剥离的元素数量)
19 Retry Request 主要用于重试,但需要 Retries、Statuses、Methods、Series 等参数
Retries:重试的次数
Statuses:重试的 HTTP 状态码(通过 org.springframework.http.HttpStatus 表示)
Methods:重试的 HTTP 状态码(通过 org.springframework.http.HttpMethod 表示)
Series:重试的状态码(通过 org.springframework.http.HttpStatus.Series 表示)
20 RequestSize Request 用于限制请求大小,当请求超过限制时启用,限制请求达到下游服务,该过滤器将 RequestSize 作为参数
AddRequestHeader(在请求头中添加自定义的键值对)

AddRequestHeader 即主要在请求头中来添加自定义的键值对,其主要将应用过滤器 AddRequestHeader=X-Request-Name,X-Request-Value 应用并添加至请求头中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
spring:
application:
name: Gateway
cloud:
gateway:
routes:
- id: /guonei
uri: http://news.baidu.com
predicates:
- Method=GET
filters:
- AddRequestHeader=X-Request-Name,X-Request-Value

server:
port: 8210

logging:
level:
ROOT: DEBUG

.AddRequestHeader 会将 X-Request-Name=X-Request-Value 标头添加到所有请求头中。

AddRequestParameter (添加请求参数)

AddRequestParameter 主要的作用就是在请求头(Header)中添加请求参数的键值对,即将 RouteDefinition /guonei 过滤器 _genkey_0=KEY_NAME, _genkey_1=KEY_VALUE 应用在 AddRequestParameter (添加请求参数)中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
spring:
application:
name: Gateway
cloud:
gateway:
routes:
- id: /guonei
uri: http://news.baidu.com
predicates:
- Method=GET
filters:
- AddRequestParameter=KEY_NAME,KEY_VALUE

server:
port: 8210

logging:
level:
ROOT: DEBUG

这会将 KEY_NAME=KEY_VALUE 添加到所有匹配请求的下游请求所查询的字符串中,AddRequestParameter 即添加请求参数会用于匹配路径或主机的 URI 变量。

AddResponseHeader (添加响应头)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
spring:
application:
name: Gateway
cloud:
gateway:
routes:
- id: /guonei
uri: http://news.baidu.com
predicates:
- Method=GET
filters:
- AddResponseHeader=X-Response-Name,X-Response-Value

server:
port: 8210

logging:
level:
ROOT: DEBUG

此刻 AddResponseHeader 会将 X-Response-Name=X-Response-Value 所添加至响应头中。

GlobalFilter (全局过滤器)

另一种则为全局过滤器(GlobalFilter)这种过滤器与网关过滤器的区别是会 应用到所有路由中,在 Gateway 内置中,有九种全局过滤器:

Id Name Info
1 Forward Routing Filter 在 exchange 的 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 属性值中查找 URI(如果 URI 是 forward 协议,则将它用于 DispatcherHandler (调度程序处理程序) 处理请求)
2 LoadBalancerClient Filter 在 exchange 的 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 值中查找 URI,如果 URI 是 lb 协议,则会使用 Spring cloud LoadBalancerClient 将名称(lb://myservice 中的 myservice)解析为实际的主机和端口,并替换 URI 中相同属性。(除此过滤器还会查看 ServerWebExchangeU体力是。GATEWAY_SCHEME_PREFIX_ATTR 属性来判断他是否等于 lb
3 Netty Routing Filter 假设 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 中的 URI 使用的是 HTTP 或 HTTPS 协议,则运行 Netty Routing Filter。他用 Netty HttpClient 所发出的下游代理请求。相应应该放在 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR 的 exchange 中以便在以后的过滤器中使用
4 Netty Write Response Filter ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR 值中存在 NettyHttpClientResponse 则会运行 Netty Write Response Filter。(他在所有其他过滤器完成后运行,并将代理相应写回到网关客户端的响应数据中)
5 RouteToRequestUriFilter 如果 ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR 值中存在 Route 对象,则会将路由到请求地址,他会根据请求 URI 创建一个新的 URI。新的 URI 则会位于 ServerWebExchangeUtils.GATEWAY_REQUEST_URI_ATTR 值中(假设 URI 具有协议前缀,如 lb:ws://serviceid 则会将从 URI 中所剥离 lb 协议,并防止在 ServerWebExchangeUtils.GATEWAY_SCHEMEPREFIX_ATTR 中以便稍后在过滤器中所使用)
6 Websocket Routing Filter 假设 ServerWebExhcangeUtils.GATEWAY_REQUEST_URL_ATTR 值中的 URI 是 ws 或 wss 协议,则运行 Websocket Routing Filter (利用 Spring Web Socket 底层代码将 WebSocket 请求转发到下游)
也可以通过 URI 前面添加 lb 来对 Websocket 来进行负载均衡,如 lb:ws://serviceid(需要注意的是如果在普通 HTTP 上使用 SockJS 来作为回退,则会匹配正常的 HTTP 路由以及 Websocket 路由)
7 Gateway Metrics Filter 使用需要添加 spring-boot-starter-actuator 依赖,默认会通过 spring.cloud.gateway.mertics.enable 设置为 false Gateway Metrics Filter 才会运行。该过滤器会添加一个名为 gateway.request 指标(Metrics),并包含四个属性:
routeId:路由器 ID
routeUri:API将会被路由转到 URI
outcome:由 HttpStatus.Series 所分类的结果
status:HTTP 请求返回给客户端的状态
8 Combined Global Filter and GatewayFilter Ordering(组合是全局过滤器和网管过滤器排序) 当请求进入并匹配到一个路由时, Filtering Web Handler 会将 GlobalFilter 的所有实例和 GatewayFilter 的所有路由特定实例添加到过滤器链中。(这个组合的过滤器链由 org.springframeworking.core.Ordered 接口的排序,并通过 gegOrder() 方法或注解 @Order 来设置)同时网关也会对过滤器逻辑执行的 “PRE” 和 ”POST“ 阶段来进行区分
9 Marking An Exchange As Routed (路由交换) 网关在路由 WEB 服务交换后(ServerWebExchange),会将 Gateway Already Routed 添加到 exchange 属性来将该交换标识为 ”路由”(一旦被请求标识为路由,则其他的路由过滤器会跳过该请求,也可以通过便携方法将交换标识为路由,或检查交换是否已经成为路由)

路由容错

路由的容错主要分为两种,分别为需要处理为定义路由、之后通过 Hystrix 来处理路由的熔断,这也是路由容错最为核心的一点

处理未定义路由

处理未定义路由所代表的就是当路由并不存在时,所返回的错误信息,他的目的就是所提供的报错信息来对用户或开发人员给出有效的反馈。

本文使用《江雪分析公开知识存储库知识共享许可证》进行发布